﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace AbstraX
{
    internal enum DataType
    {
        StringType,
        IntegerType,
        FloatType,
    }

    internal static class EventMessageHelper
    {
        private const int PARM_COUNT_WIDTH = 2;

        internal static void WriteTo(this EventMessage eventMessage, Message message, params object[] parms)
        {
            var stream = new MemoryStream();
            var writer = new BinaryWriter(stream);

            // first int is number of parms

            writer.Write(parms.Length);

            eventMessage.Message = message;

            // order: datatype, length, data

            foreach (var parm in parms)
            {
                switch (parm.GetType().Name.ToLower())
                {
                    case "string":
                        {
                            var value = (string)parm;

                            writer.Write((int)DataType.StringType);
                            writer.Write(value.Length + 1);
                            writer.Write(value);

                            break;
                        }
                    case "int32":
                        {
                            var value = (int)parm;

                            writer.Write((int)DataType.IntegerType);
                            writer.Write(4);
                            writer.Write(value);

                            break;
                        }
                    case "single":
                        {
                            var value = (float)parm;

                            writer.Write((int)DataType.FloatType);
                            writer.Write(4);
                            writer.Write(value);

                            break;
                        }
                    default:
                        Debugger.Break();
                        break;
                }
            }

            writer.Flush();

            eventMessage.EventArgs = new byte[(int)stream.Length];

            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(eventMessage.EventArgs, 0, (int)stream.Length);

            writer.Close();
            stream.Close();
        }

        internal static object[] ReadFrom(this EventMessage eventMessage)
        {
            var stream = new MemoryStream(eventMessage.EventArgs.Length);
            var reader = new BinaryReader(stream);
            var count = 0;
            object[] messageObjects;

            stream.Write(eventMessage.EventArgs, 0, eventMessage.EventArgs.Length);
            stream.Seek(0, SeekOrigin.Begin);

            count = reader.ReadInt32();
            messageObjects = new object[count];

            for (var x = 0; x < count; x++)
            {
                var dataType = (DataType)reader.ReadInt32();
                var length = reader.ReadInt32();

                switch (dataType)
                {
                    case DataType.StringType:

                        //var stringLength = reader.ReadByte();
                        //var bytes = reader.ReadBytes(stringLength);

                        messageObjects[x] = reader.ReadString();

                        //messageObjects[x] = UTF8Encoding.UTF8.GetString(bytes, 0, stringLength);

                        break;

                    case DataType.IntegerType:

                        messageObjects[x] = reader.ReadInt32();
                        break;

                    case DataType.FloatType:

                        messageObjects[x] = reader.ReadSingle();
                        break;
                }
            }

            reader.Close();
            stream.Close();

            return messageObjects;
        }
    }
}
